package data_structures;

import Utilities.Constants;

/**
 * Represents a hyper-parameter configuration. A configuration consists of a
 * several hyper-parameters and their values.
 */
public class HPConfiguration {
	private HyperParameter[] hyperParameters;

	/**
	 * @param hyperParameters
	 *            Hyper-parameters that defines the configuration
	 */
	public HPConfiguration(HyperParameter[] hyperParameters) {
		this.hyperParameters = hyperParameters;
	}

	/**
	 * A neighbor of a configuration is a random successor of the configuration
	 * in the configuration space. It will be useful in local search algorithms
	 * where we search for the best configuration.
	 * 
	 * @return A random neighbor of the configuration.
	 */
	public HPConfiguration getRandomNeighbor() {
		HyperParameter[] hyperParametersClone = hyperParameters.clone();

		int randomHPIndex = Constants.RANDOM
				.nextInt(hyperParametersClone.length);

		HyperParameter hyperParameter = hyperParametersClone[randomHPIndex]
				.getRandomNeighbor();

		hyperParametersClone[randomHPIndex] = hyperParameter;

		return new HPConfiguration(hyperParametersClone);
	}

	/**
	 * @return the hyperParameters
	 */
	public HyperParameter[] getHyperParameters() {
		return hyperParameters;
	}

	public int hashCode() {
		int hashVal = 0;

		for (HyperParameter hyperParameter : hyperParameters)
			hashVal += hyperParameter.hashCode();

		return hashVal;
	}

	public boolean equals(HPConfiguration hpConf) {

		if (hpConf.hyperParameters.length != this.hyperParameters.length)
			return false;

		HyperParameter[] rhsHPParams = hpConf.hyperParameters;

		for (int i = 0; i < rhsHPParams.length; ++i) {
			if (!rhsHPParams[i].equals(hyperParameters[i]))
				return false;
		}

		return true;
	}

	/**
	 * 
	 * @return Number of hyper-parameters in this configuration.
	 */
	public int size() {
		return hyperParameters.length;
	}

	public String toString() {
		String str = "Configuration: ";

		for (HyperParameter hp : hyperParameters) {
			str += hp.toString() + "\t";
		}

		return str;
	}
}
